/***************************************************
 * const的一般用法总结：
 * const一般用在如下场景中：
 *     1、const修饰基本数据类型
 *     2、const修饰函数
 *     3、const修饰类
 *     4、const修饰类对象
 * 使用const是一个好习惯，除非你有充足的理由拒绝它
 * *************************************************/
#include<iostream>
using namespace std;

struct Student {
    int age;
    char* name;
};
/*****************************************************
 * const修饰基本数据类型
 *   1、如果const修饰的星号*在变量左侧，表明该变量不可改变
 *   2、如果const修饰的星号*在变量右侧，变量该变量的值不可改变
 ****************************************************/
void test1()
{
    int a = 9;
    const int temp = 10;
    const int arr[3] = {1, 2, 3};
    const int* ptr1 = &a;    // ptr1的内容不可改变  *ptr1 = 12，错误！
    int* const ptr2 = &a;
}

/**********************************************
 * const修饰一般函数
 *   1、const修饰函数参数：通常用于参数是指针或者引用的情况
 *   2、const修饰函数返回值
 * *******************************************/
void test2(const Student& stu)
{
    // stu中的所有变量都不可修改，只读
}

const char* test3()
{
    // 说明函数的返回值是不可修改的变量
}
char* const test3()
{
    // 说明函数的返回值是指针，指针变量不能修改
}

/****************************************************************************
 * const修饰成员函数和成员变量
 *   1、const修饰成员函数放在类::成员函数 const，const一般
 *      放在函数后面，为什么放后面大概是因为其他地方都被占用了
 *   2、const修饰的成员函数，不能修改类的数据成员
 *   3、const修饰的成员函数，不能调用非const的成员函数
 *   4、const修饰的成员函数，必须在声明和定义出分别加上const，
 *   5、const修饰的成员变量，只能通过类的初始化列表进行初始化，只能这一种办法！！！
 * **************************************************************************/
class Base {
public:
    Base()
    {
        age = 9;  // 错误，age是const成员变量，只能通过成员列表赋值
    }
    ~Base();
    int get_count() const
    {
        ++count; // 错误，不能修改成员变量的值
        show(); // 错误，不能调用非const成员变量
        return count;
    }
    void show()
    {
        cout << count << endl;
    }
private:
    const int age;
    int count;
};

/**************************************************************
 * const修饰类对象
 *   1、const修饰类对象，对象只能引用const的成员函数和const成员变量
 * ************************************************************/

int main()
{
    const Base ba;
    ba.get_count();
    ba.show();  // 错误，ba只能引用const修饰的成员函数
    return 0;
}